package main

import (
	"encoding/base64"
	"flag"
	"fmt"
	"io/ioutil"
	"os"
	"strings"

	robot "github.com/go-vgo/robotgo"
	. "github.com/soekchl/myUtils"
)

var (
	startKey         = `Content-Type: image/jp` // 图片关键字
	startEndKey      = `.jp`                    // base64 图片数据开始关键字
	stopKey          = `---`                    // base64 图片数据结束关键字
	readFileBuffSize = 1024 * 1024 * 128        // 128 MB
	scale            = 125                      // 屏幕放大比例

	scorlX    = 1908 // 右边滚动条 x 坐标
	NextPageX = 1885 // 下一页 x 坐标
	NextPageY = 984  // 下一页 y 坐标

	count = flag.Int("count", 10, "缓存页面页数")
	mode  = flag.Int("mode", 0, "模式 0-下载转换 1-下载 2-转换")
)

func init() {
	flag.Parse()
}

func main() {
	switch *mode {
	case 1:
		download()
	case 0:
		download()
		fallthrough
	default:
		mhtmlToJpeg()
	}
	return

}

func download() {
	realCount := 0
	editNextPageX()
	go checkExit()

	for ; realCount < *count; realCount++ {
		openNextPage()
		if checkNoNewPage() {
			robot.KeyTap(robot.Enter)
			buffImages(4)
			break
		}
		buffImages(4)
		tabPage()
	}

	Info("开始保存")
	tabPage()
	for i := 0; i <= realCount; i++ {
		buffImages(2)
		robot.KeyTap(robot.KeyS, robot.Ctrl, "command")
		robot.MilliSleep(300)
		robot.KeyTap(robot.Enter)
		robot.MilliSleep(300)
		tabPage()
	}
}

// 修改下一页的坐标
func editNextPageX() {
	Info("3秒内 把鼠标移动到下一页坐标处")
	robot.Sleep(3)
	NextPageX, NextPageY = robot.GetMousePos()
	Infof("下一页 坐标：%v %v", NextPageX, NextPageY)
}

// 检测鼠标是否有移动  移动鼠标就表示 退出
func checkExit() {
	x, y := 0, 0
	robot.Sleep(1)
	abs := func(n int) int {
		if n < 0 {
			return -n
		}
		return n
	}
	for {
		robot.MicroSleep(1)
		x, y = robot.GetMousePos()
		// Info(x, y)
		if abs(scorlX-x) > 10 && abs(NextPageX-x) > 10 {
			Info("退出程序 鼠标坐标 ", x, y)
			os.Exit(1)
		}
	}
}

// 缓存整个页面
func buffImages(count int) {
	yMin := 175
	yMax := 985
	speed := 2.0

	robot.Move(scorlX*100/scale, yMin*100/scale)
	for i := 0; i < count; i++ {
		robot.MilliSleep(50)
		robot.MouseDown("left")
		robot.MoveSmooth(scorlX*100/scale, yMax*100/scale, speed, speed)
		robot.MilliSleep(300)
		robot.MoveSmooth(scorlX*100/scale, yMin*100/scale, speed, speed)
		robot.MouseUp("left")
	}

}

// ctrl + tab
func tabPage() {
	robot.KeyTap(robot.Tab, robot.Ctrl, "command")
	robot.MilliSleep(300)
}

// 打开下一页
func openNextPage() {
	robot.Move(NextPageX*100/scale, NextPageY*100/scale)
	robot.KeyToggle(robot.Ctrl, robot.Down)
	robot.MouseClick(`left`, false)
	robot.KeyToggle(robot.Ctrl, robot.Up)
	robot.MilliSleep(300)
}

func mhtmlToJpeg() {
	Info("转换")
	// 目录搜索
	d, err := ioutil.ReadDir(".")
	if err != nil {
		Error("ioutil.ReadDir", err)
		return
	}

	for _, v := range d {
		if !strings.Contains(v.Name(), ".mhtml") {
			continue
		}
		n := getNumberFromStr(v.Name())
		n -= 1 // 漫画从0开始
		if n < 0 {
			Warnf("not change name=%v", v.Name())
			continue
		}
		dir := fmt.Sprintf("./comic/%v", n)
		os.MkdirAll(dir, os.ModePerm)

		err = procOneMhtml(v.Name(), dir)
		if err != nil {
			Error(err)
			return
		} else {
			Noticef("%v ok!", v.Name())
		}
	}
}

func procOneMhtml(fileName, outDir string) error {

	// 搜索文件中关键字  和 总个数
	f, err := os.Open(fileName)
	if err != nil {
		return fmt.Errorf("os.Open", fileName, err)
	}
	defer f.Close()

	buff := make([]byte, readFileBuffSize)
	n, err := f.Read(buff)
	if err != nil {
		return fmt.Errorf("os.Open %v %v ", fileName, err)
	}
	if n >= readFileBuffSize {
		return fmt.Errorf("readFileBuffSize smail %v", fileName)
	}

	max := strings.Count(string(buff), startKey)
	if max < 1 {
		return fmt.Errorf("not found key=%v %v", startKey, fileName)
	}

	Infof("fileName=%v n=%v max=%v", fileName, n, max)

	startIdx, nowIndex, endIdx := 0, 0, 0

	for ; max > 0; max -= 1 {
		startIdx = getStartIdx(buff)
		if startIdx < 1 {
			return fmt.Errorf("getStartIdx error max=%v", max)
		}
		buff = buff[startIdx:]
		startIdx = 0
		endIdx = strings.Index(string(buff), stopKey) - 1
		nowIndex = endIdx

		// Debugf("s=%v e=%v buff=%v", startIdx, endIdx, string(buff[:100]))

		// 按照倒序保存  图片是从1开始 IMGE_1.jpeg
		err = base64ToFile(
			string(buff[startIdx:endIdx]),
			fmt.Sprintf("%v/IMGE_%v.jpeg", outDir, max),
		)
		if err != nil {
			return fmt.Errorf("base64ToFile %v", err)
		}
		buff = buff[nowIndex:]
	}

	return nil
}

func getStartIdx(buff []byte) int {
	s := strings.Index(string(buff), startKey)
	if s < 1 {
		return s
	}

	tmp := strings.Index(string(buff[s:]), startEndKey)
	if tmp < 1 {
		Errorf("not found key=.")
		return tmp
	}
	return s + tmp + 4
}

// 检测弹窗是否弹出
func checkNoNewPage() bool {
	return ("0b57d0" == robot.GetPixelColor(1142, 232) &&
		"0b57d0" == robot.GetPixelColor(1210, 232)) ||
		("0d50bb" == robot.GetPixelColor(1142, 232) &&
			"0d50bb" == robot.GetPixelColor(1210, 232))
}

func base64ToFile(base64SrcStr, outputFileName string) error {
	by, err := base64.StdEncoding.DecodeString(base64SrcStr)
	if err != nil {
		return fmt.Errorf("base64.StdEncoding.DecodeString %v %v", outputFileName, err)
	}

	f, err := os.OpenFile(outputFileName, os.O_CREATE, 0644)
	if err != nil {
		return fmt.Errorf("os.OpenFile %v %v", outputFileName, err)
	}
	defer f.Close()

	_, err = f.Write(by)
	if err != nil {
		err = fmt.Errorf("f.Write %v %v", outputFileName, err)
	}
	return err
}

// 文字转数字  第150话-->150
func getNumberFromStr(str string) (num int) {
	for _, v := range str {
		// 数字
		if v >= rune('0') && rune('9') >= v {
			num = num*10 + int(v-'0')
		}
	}
	return
}
